#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <err.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h> 
#include <signal.h>

#include <event.h>
#include <evhttp.h>

#define SEND_BUFFER_SIZE     1024
#define SERVER_PORT          9889

struct evhttp *httpd;

/* Signal handler function (defined below). */
static void sighandler(int signal);

static void sighandler(int signal) {
    fprintf(stdout, "Received signal %d: %s.  Shutting down.\n", signal, strsignal(signal));
	evhttp_free(httpd);
}

    void
root_handler(struct evhttp_request *req, void *arg)
{
    struct evbuffer *buf;

    buf = evbuffer_new();
    if (buf == NULL)
        err(1, "failed to create response buffer");
    evbuffer_add_printf(buf, "Hello World!/n");
    evhttp_send_reply(req, HTTP_OK, "OK", buf);
}

    void
generic_handler(struct evhttp_request *req, void *arg)
{
    struct evbuffer *buf;
	char *cmdtype;
	struct evkeyvalq *headers;
	struct evkeyval *header;
	int fd = -1;
	struct stat st;
	char data[SEND_BUFFER_SIZE + 1];
	int bytes_read = -1;
//	char* method = NULL;
//	char* filename = NULL;
	
    buf = evbuffer_new();
    if (buf == NULL)
        err(1, "failed to create response buffer");
	
	switch (evhttp_request_get_command(req)) {
	case EVHTTP_REQ_GET: cmdtype = "GET"; break;
	case EVHTTP_REQ_POST: cmdtype = "POST"; break;
	case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
	case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
	case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
	case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
	case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
	case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
	case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
	default: cmdtype = "unknown"; break;
	}
	printf("Received a %s request for %s\nHeaders:\n",
	    cmdtype, evhttp_request_get_uri(req));
	
	headers = evhttp_request_get_input_headers(req);
	for (header = headers->tqh_first; header;
	    header = header->next.tqe_next) {
		printf("  %s: %s\n", header->key, header->value);
	}
	
//###### GET处理 ############################################
	struct evkeyvalq params;
	const char *uri = evhttp_request_uri(req);
	evhttp_parse_query(evhttp_decode_uri(uri), &params);
	const char* method = evhttp_find_header(&params, "method");
	if(NULL == method)
	{
		goto badrequest;
	}
	const char* filename = evhttp_find_header(&params, "file");
	if(NULL == filename)
	{
		goto badrequest;
	}
//##########################################################
//############## POST处理 ##################################
char *post_data = (char *) EVBUFFER_DATA(req->input_buffer);
printf("PostData:%s\n", post_data);
//##########################################################	
		
	
	if ((fd = open(filename, O_RDONLY)) < 0) {
			printf("not found %s\n", filename);
			goto err;
		}

		if (fstat(fd, &st)<0) {
			/* Make sure the length still matches, now that we
			 * opened the file :/ */
			printf("fstat error\n");
			goto err;
		}
		
	evhttp_add_header(req->output_headers, "Content-Type", "text/plain");
	
	evhttp_add_header(req->output_headers, "Location", "http://www.csdn.net/");
//	evhttp_add_header(req->output_headers, "refresh", "1; url=http://www.oschina.net/");
	printf("#################################\n");
	headers = evhttp_request_get_output_headers(req);
	for (header = headers->tqh_first; header;
	    header = header->next.tqe_next) {
		printf("  %s: %s\n", header->key, header->value);
	}
	
//    evbuffer_add_printf(buf, "Requested: %s/n", evhttp_request_uri(req));
	
//	evbuffer_add_file(buf, fd, 0, st.st_size);
	
    evhttp_send_reply_start(req, HTTP_OK, "OK");

	
	memset(data, 0, sizeof(data));
	while(bytes_read = read(fd, data, SEND_BUFFER_SIZE))
	{
		/* 一个致命的错误发生了 */  
        if ((bytes_read == -1) && (errno != EINTR)) break;  
		else if (bytes_read > 0) {
			evbuffer_add_printf(buf, "%s", data);
			evhttp_send_reply_chunk(req, buf);
		}		
	}	
	
	evhttp_send_reply_end(req);
	goto done;
badrequest:
	evhttp_send_error(req, HTTP_BADMETHOD, "Bad Request");
	goto done;
err:
	printf("Not Found\n");
	evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found");
	if (fd>=0)
		close(fd);
done:
if (buf)
		evbuffer_free(buf);
if (fd>=0)
		close(fd);
}

int main(int argc, char **argv)
{
    
	
	/* Set signal handlers */
	sigset_t sigset;
	sigemptyset(&sigset);
	struct sigaction siginfo = {
		.sa_handler = sighandler,
		.sa_mask = sigset,
		.sa_flags = SA_RESTART,
	};
	sigaction(SIGINT, &siginfo, NULL);
	sigaction(SIGTERM, &siginfo, NULL);
	
    event_init();
    httpd = evhttp_start("0.0.0.0", SERVER_PORT);
	printf("Listening on %d\n", SERVER_PORT);
	
	
    /* Set a callback for requests to "/". */
    evhttp_set_cb(httpd, "/", root_handler, NULL);

    /* Set a callback for all other requests. */
    evhttp_set_gencb(httpd, generic_handler, NULL);

    event_dispatch();

    /* Not reached in this code as it is now. */

//    evhttp_free(httpd);

    return 0;
}
